#include <math.h>
#include <stdio.h>
#include <fstream>
#include <string>
#include <iostream>
using namespace std;

#include "Math/Functor.h"
#include "Math/Factory.h"
#include "Math/Minimizer.h"

//#include "TASImage.h"
#include "TAxis.h"
#include "TColor.h"
#include "TCut.h"
#include "TCanvas.h"
#include "TChain.h"
#include "TDatabasePDG.h"
#include "TDecompLU.h"
#include "TDecompSVD.h"
#include "TDirectory.h"
#include "TEventList.h"
#include "TF1.h"
#include "TF2.h"
#include "TFile.h"
#include "TGaxis.h"
#include "TGeoManager.h"
#include "TGeoGlobalMagField.h"
#include "TRandom3.h"
#include "TGraph.h"
#include "TGraphAsymmErrors.h"
#include "TGraphErrors.h"
#include "TGraphPolar.h"
#include "TGrid.h"
#include "TH1F.h"
#include "TH2F.h"
#include "TH1D.h"
#include "TH2D.h"
#include "TH3D.h"
#include "THnSparse.h"
#include "TLatex.h"
#include "TLegend.h"
#include "TLegendEntry.h"
#include "TLinearFitter.h"
#include "TMarker.h"
#include "TMath.h"
#include "TMatrixD.h"
#include "TMinuit.h"
#include "TPaletteAxis.h"
#include "TPaveText.h"
#include "TPolyMarker.h"
#include "TProfile.h"
#include "TROOT.h"
#include "TStopwatch.h"
#include "TString.h"
#include "TStyle.h"
#include "TSystem.h"
#include "TSystemDirectory.h"
#include "TTree.h"
#include "TTimeStamp.h"
#include "TUUID.h"
#include "TVector3.h"
#include "TVectorD.h"
#include "TVirtualPad.h"

#include "style.h"
#include "XGLUtils.h"

#define EPSILON 1e-12

Double_t style::fgkTextSize = 0.05;
Double_t style::fgkTitleSize = 0.05;
Double_t style::fgkMarkerSize = 1;
Double_t style::fgkLineWidth = 2;
Int_t style::fgkTextFont = 42;
Double_t style::fgkLabelOffset = 0.01;
Double_t style::fgkXTitleOffset = 1.25;//1.1;//1.25;
Double_t style::fgkYTitleOffset = 1.1;//1.2;
Double_t style::fgkTickLength = 0.02;

ClassImp(style);

Bool_t style::GetGrPointLimits(const TGraphAsymmErrors * gr, Double_t & gmin, Double_t & gmax, Bool_t & klogx)
{
  return XGLUtils::GetGrPointLimits(gr, gmin, gmax, klogx);
}

Bool_t style::SimpleInterpolate(const Double_t x0, const Double_t x1, const Double_t y0, const Double_t y1, const Double_t xx, Double_t & yy, const Bool_t ksteep, const Bool_t klogx)
{
  //trully small leading to nan, make Ninwindow = 0, skip the graph                                                                                                                                                                                  
  if(y0<EPSILON || y1<EPSILON)
    return kFALSE;

  if(ksteep){
    //steeply falling, be careful, check in ratio panel!                                                                                                                                                                                             
    Double_t kk = (log10(y1)-log10(y0));
    if(klogx){
      kk /= TMath::Log10(x1/x0);
      yy = TMath::Power(10, kk*TMath::Log10(xx/x0)+log10(y0) );
    }
    else{
      kk /= (x1-x0);
      yy = TMath::Power(10,kk*(xx-x0)+log10(y0));
    }
  }
  else{
    Double_t kk = (y1-y0);
    if(klogx){
      kk /= TMath::Log10(x1/x0);
      yy = kk*TMath::Log10(xx/x0)+y0;
    }
    else{
      kk /= (x1-x0);
      yy = kk*(xx-x0)+y0;
    }
  }
  return kTRUE;
}

Int_t style::GetCommonLimits(const Int_t ngr, const TGraphAsymmErrors * grs[], Int_t id0s[], Int_t id1s[])
{
  return XGLUtils::GetCommonLimits(ngr, grs, id0s, id1s);
}

void style::SimpleScaleToRef(const TGraphAsymmErrors * grStat, const TGraphAsymmErrors * grSys, const TGraphAsymmErrors * grRef, TGraphAsymmErrors *& outStat, TGraphAsymmErrors * & outSys)
{
  XGLUtils::SimpleScaleToRef(grStat, grSys, grRef, outStat, outSys, kTRUE);
}

void style::ScaleToRef(const TGraphAsymmErrors * grStat, const TGraphAsymmErrors * grSys, const TGraphAsymmErrors * grRef, const Bool_t ksteep, TGraphAsymmErrors *& outStat, TGraphAsymmErrors * & outSys)
{

  TGraphAsymmErrors * tmpStat = (TGraphAsymmErrors *) grStat->Clone(Form("ratio%s",grStat->GetName()));
  TGraphAsymmErrors * tmpSys  = (TGraphAsymmErrors *) grSys->Clone(Form("ratio%s",grSys->GetName()));

  Double_t rmin = -999;
  Double_t rmax = -999;
  Bool_t klogx = kFALSE;
  const Bool_t kup = GetGrPointLimits(grRef, rmin, rmax, klogx);

  for(Int_t ip=0; ip<tmpStat->GetN(); ip++){
    const Double_t xx = tmpStat->GetX()[ip];

    Double_t x0=-999, x1=-999, y0=-999, y1=-999;
    if(xx>=rmin && xx<=rmax){ 
      //interpolation
      for(Int_t it=1; it<grRef->GetN(); it++){
        x0 = grRef->GetX()[it-1];
        x1 = grRef->GetX()[it];
        if((x0<=xx && x1>= xx) || (x0>=xx && x1<=xx)){
          y0 = grRef->GetY()[it-1];
          y1 = grRef->GetY()[it];
          //found and go out
          break;
        }
      }
    }
    //no overflow or underflow
    /*
    else if(xx<rmin){
      if(kup){
        x0 = grRef->GetX()[0];
        x1 = grRef->GetX()[1];
        y0 = grRef->GetY()[0];
        y1 = grRef->GetY()[1];
      }
      else{
        x0 = grRef->GetX()[grRef->GetN()-2];
        x1 = grRef->GetX()[grRef->GetN()-1];
        y0 = grRef->GetY()[grRef->GetN()-2];
        y1 = grRef->GetY()[grRef->GetN()-1];
      }
    }
    else if(xx>rmax){
      if(!kup){
        x0 = grRef->GetX()[0];
        x1 = grRef->GetX()[1];
        y0 = grRef->GetY()[0];
        y1 = grRef->GetY()[1];
      }
      else{
        x0 = grRef->GetX()[grRef->GetN()-2];
        x1 = grRef->GetX()[grRef->GetN()-1];
        y0 = grRef->GetY()[grRef->GetN()-2];
        y1 = grRef->GetY()[grRef->GetN()-1];
      }
    }
    */

    //y of ref
    Double_t yINT = -999;    

    if(y0<-990 && y1<-990){
      printf("ScaleToRef::bad interpolation, not found!! name %s title %s ip %d xx %e -- x0 %e x1 %e y0 %e y1 %e -- kup %d klogx %d rmin %e rmax %e\n", grStat->GetName(), grStat->GetTitle(), ip, xx, x0, x1, y0,y1, kup, klogx, rmin, rmax); //exit(1);
    }
    else{
      if(ksteep){
        //steeply falling, be careful, check in ratio panel!                                                                                                                                                                                             
        Double_t kk = (log10(y1)-log10(y0));
        if(klogx){
          kk /= TMath::Log10(x1/x0);
          yINT = TMath::Power(10, kk*TMath::Log10(xx/x0)+log10(y0) );
        }
        else{
          kk /= (x1-x0);
          yINT = TMath::Power(10,kk*(xx-x0)+log10(y0));
        }
      }
      else{
        Double_t kk = (y1-y0);
        if(klogx){
          kk /= TMath::Log10(x1/x0);
          yINT = kk*TMath::Log10(xx/x0)+y0;
        }
        else{
          kk /= (x1-x0);
          yINT = kk*(xx-x0)+y0;
        }
      }
    }
    
    if(yINT<-990 || fabs(yINT)<EPSILON){
      printf("ScaleToRef::interpolation fail at name %s title %s ip %d ngr %d xx %e yINT %e\n", grStat->GetName(), grStat->GetTitle(), ip, grRef->GetN(), xx, yINT);
      tmpStat->GetY()[ip]=-999;
      tmpStat->GetEYlow()[ip]=-999;
      tmpStat->GetEYhigh()[ip]=-999;
      tmpSys->GetY()[ip]=-999;
      tmpSys->GetEYlow()[ip]=-999;
      tmpSys->GetEYhigh()[ip]=-999;
    }
    else{
      tmpStat->GetY()[ip]/=yINT;
      tmpStat->GetEYlow()[ip]/=yINT;
      tmpStat->GetEYhigh()[ip]/=yINT;
      tmpSys->GetY()[ip]/=yINT;
      tmpSys->GetEYlow()[ip]/=yINT;
      tmpSys->GetEYhigh()[ip]/=yINT;
    }
  }

  outStat =  XGLUtils::PublicFilterGraph(tmpStat, -990);
  if(outStat->GetN()==0){
    printf("ScaleToRef::outStat n=0!!\n");
    for(Int_t it=0; it<grRef->GetN(); it++){
      const Double_t xx = grRef->GetX()[it];
      printf("ScaleToRef::%d %e\n", it, xx);
    }
    exit(1);
  }
  outSys =  XGLUtils::PublicFilterGraph(tmpSys, -990);

  delete tmpStat;
  delete tmpSys;
}


void style::SimpleCalcMean(TList *ll, const Bool_t ksteep)
{
  printf("\n\nSimpleCalcMean...\n");
  const Int_t ls=ll->GetSize();
  const Int_t ngr = ls/2;
  const TGraphAsymmErrors * grstat[ngr];
  const TGraphAsymmErrors * grsys[ngr];
 
  for(Int_t ii=0; ii<ngr; ii++){
    grstat[ii]=(const TGraphAsymmErrors *)ll->At(ii*2);
    grsys[ii]=(const TGraphAsymmErrors *)ll->At(ii*2+1);

    printf("SimpleCalcMean::print graphs igr %d statn %d sysn %d\n", ii, grstat[ii]->GetN(), grsys[ii]->GetN()); 
    if(!grstat[ii]->GetN() || !grsys[ii]->GetN()){
      printf("SimpleCalcMean::bad n %d %d\n", grstat[ii]->GetN(), grsys[ii]->GetN() ); exit(1);
    }
  }

  Int_t id0s[ngr];
  Int_t id1s[ngr];
  const Int_t npoint = GetCommonLimits(ngr, grstat, id0s, id1s);

  TGraphAsymmErrors * grMeanStat = new TGraphAsymmErrors;  grMeanStat->SetName("gEtaMeanStat");
  grMeanStat->SetMaximum(grstat[0]->GetMaximum());
  grMeanStat->SetMinimum(grstat[0]->GetMinimum());
  grMeanStat->SetTitle(Form("%s;%s;%s", grstat[0]->GetTitle(), grstat[0]->GetXaxis()->GetTitle(), grstat[0]->GetYaxis()->GetTitle()));
  //(TGraphAsymmErrors *) grstat[0]->Clone("gEtaMeanStat");  grMeanStat->Set(0);
  ll->Add(grMeanStat);

  TGraphAsymmErrors * grMeanSys = new TGraphAsymmErrors;  grMeanSys->SetName("gEtaMeanSys"); 
  grMeanSys->SetTitle(grMeanStat->GetTitle());
  ll->Add(grMeanSys);

  for(Int_t igr=0; igr<ngr; igr++){
    printf("SimpleCalcMean::common limits igr %d/%d id0 %d id1 %d npoint %d\n", igr, ngr, id0s[igr], id1s[igr], npoint); 
  }

  for(Int_t pp=0; pp<npoint; pp++){
    Double_t xx = -999;
    Double_t exl = -999;
    Double_t exh = -999;

    Double_t ysum = 0;
    Double_t statsum2 = 0;
    Double_t syslsum2 = 0;
    Double_t syshsum2 = 0;
    Double_t maxy = -1e10;
    Double_t miny = 1e10;
    for(Int_t igr=0; igr<ngr; igr++){
      const Int_t tmpid = id0s[igr]+pp;
      //xx
      const Double_t tmpxx = grstat[igr]->GetX()[tmpid];
      if(xx<0){
        xx = tmpxx;
      }
      else if(fabs(xx-tmpxx)>EPSILON){
        printf("SimpleCalcMean::wrong x at igr %d ip %d xx %e tmpxx %e\n", igr, pp, xx, tmpxx); exit(1);
      }

      //exl
      const Double_t tmpexl = grstat[igr]->GetEXlow()[tmpid];
      if(exl<0){
        exl = tmpexl;
      }
      else if(fabs(exl-tmpexl)>EPSILON){
        printf("SimpleCalcMean::wrong x at igr %d ip %d exl %e tmpexl %e\n", igr, pp, exl, tmpexl); exit(1);
      }

      //exh
      const Double_t tmpexh = grstat[igr]->GetEXhigh()[tmpid];
      if(exh<0){
        exh = tmpexh;
      }
      else if(fabs(exh-tmpexh)>EPSILON){
        printf("SimpleCalcMean::wrong x at igr %d ip %d exh %e tmpexh %e\n", igr, pp, exh, tmpexh); exit(1);
      }

      //yy
      const Double_t y0 = grstat[igr]->GetY()[tmpid];;
      const Double_t yy = ksteep? TMath::Log10(y0) : y0;
      ysum+=yy;

      if(y0>maxy) maxy = y0;
      if(y0<miny) miny = y0;

      //ystat
      const Double_t ystat = grstat[igr]->GetEYlow()[tmpid];
      statsum2 += ystat*ystat;

      //ysysl
      const Double_t ysysl =grsys[igr]->GetEYlow()[tmpid];
      //syslsum2 += ysysl*ysysl;
      syslsum2 += ysysl;

      //ysysh
      const Double_t ysysh = grsys[igr]->GetEYhigh()[tmpid];
      //syshsum2 += ysysh*ysysh;
      syshsum2 += ysysh;
    }
    ysum /= ngr;
    const Double_t ymean = ksteep? TMath::Power(10, ysum) : ysum;

    const Double_t eystat = TMath::Sqrt(statsum2)/ngr;

    const Double_t eysysl0 = syslsum2/ngr; //TMath::Sqrt(syslsum2)/ngr;
    const Double_t eysysh0 = syshsum2/ngr; //TMath::Sqrt(syshsum2)/ngr;
    const Double_t totsysl = TMath::Sqrt(eysysl0*eysysl0 + (ymean-miny)*(ymean-miny));
    const Double_t totsysh = TMath::Sqrt(eysysh0*eysysh0 + (maxy-ymean)*(maxy-ymean));

    grMeanStat->SetPoint(pp, xx, ymean);
    grMeanSys->SetPoint(pp, xx, ymean);

    grMeanStat->SetPointError(pp, exl, exh, eystat, eystat);
    grMeanSys->SetPointError(pp, exl, exh, totsysl, totsysh);
  }
  printf("=====> SimpleCalcMean done!!\n\n");
}


//========================

TGraphAsymmErrors * style::GetInverse(const TGraphAsymmErrors * graw)
{
  TGraphAsymmErrors * ginv = (TGraphAsymmErrors*) graw->Clone(Form("%sInv", graw->GetName()));

  const Int_t np = graw->GetN();

  Int_t ipoint = 0;
  for(Int_t ii=0; ii<np; ii++){
    const Double_t xx = graw->GetX()[ii];
    const Double_t exl = graw->GetEXlow()[ii];
    const Double_t exh = graw->GetEXhigh()[ii];

    const Double_t tmpyy = graw->GetY()[ii];
    const Double_t tmpeyl = graw->GetEYlow()[ii];
    const Double_t tmpeyh = graw->GetEYhigh()[ii];

    if(tmpyy<EPSILON)
      continue;

    const Double_t yy = 1/tmpyy;
    const Double_t eyl = yy * tmpeyl/tmpyy;
    const Double_t eyh = yy * tmpeyh/tmpyy;

    ginv->SetPoint(ipoint, xx, yy);
    ginv->SetPointError(ipoint, exl, exh, eyl, eyh);
    ipoint++;
  }

  ginv->Set(ipoint);

  //have to reset title, at least, after Set                                                                                                                                                                                                                 
  ginv->GetYaxis()->SetTitle(Form("inverse of %s",graw->GetYaxis()->GetTitle()));
  ginv->GetXaxis()->SetTitle(graw->GetXaxis()->GetTitle());

  return ginv;
}

void style::BinLogX(TAxis* ax)
{
  XGLUtils::BinLogX(ax);
}

TH1D * style::Func2Hist(TF1 * ff, const Bool_t klogx)
{
  TH1D * hh=0x0;
  TString hname(Form("hist%s%d", ff->GetName(), gRandom->Integer(1000)));
  if(gDirectory->Get(hname)){
    hname = Form("hist%s%d", ff->GetName(), gRandom->Integer(1000));
  }

  hh=new TH1D(hname,"",500, ff->GetXmin(), ff->GetXmax());
  if(klogx){
    BinLogX(hh->GetXaxis());
  }

  hh->SetLineColor(ff->GetLineColor());
  hh->SetLineStyle(ff->GetLineStyle());

  for(Int_t ii=1; ii<=hh->GetNbinsX(); ii++){
    const Double_t xi = hh->GetBinCenter(ii);
    const Double_t yi = ff->Eval(xi);
    hh->SetBinContent(ii, yi);
  }

  hh->GetXaxis()->SetTitle(ff->GetXaxis()->GetTitle());
  hh->GetYaxis()->SetTitle(ff->GetYaxis()->GetTitle());
  return hh;
}

void style::DividegPad(int nx, int ny, double l, double r, double t, double b)
{
  gStyle->SetPadTopMargin(0.);
  gStyle->SetPadBottomMargin(0.);
  gStyle->SetPadLeftMargin(0.);
  gStyle->SetPadRightMargin(0.); 
 
   int ix, iy, n=0;
   double x1, x2, y1, y2;
   double dx = ((1-r)*(1-l))/((1-r)*(1-l)*(nx-2)-r+2-l);
   double dl = dx/(1-l);
   double dy = ((1-t)*(1-b))/((1-t)*(1-b)*(ny-2)-t+2-b);
   double db = dy/(1-b);
   char *name  = new char [strlen(gPad->GetName())+6];

   y1 = 0;
   y2 = db;
   for (iy=0; iy<ny; iy++) {
      x1 = 0;
      x2 = dl;
      for (ix=0;ix<nx;ix++) {
         if (x1 > x2) continue;
         n++;
         sprintf(name,"%s_%d",gPad->GetName(),n);
         TPad *pad = new TPad(name,name,x1,y1,x2,y2,0);
         if (ix==0)    pad->SetLeftMargin(l);
         if (ix==nx-1) pad->SetRightMargin(r);
         if (iy==ny-1) pad->SetTopMargin(t);
         if (iy==0)    pad->SetBottomMargin(b);
         x1 = x2;
         if (ix==nx-2) x2 = 1;
         else          x2 = x1+dx;
         pad->SetNumber(n);
         pad->Draw();
         pad->SetTicks();
      }
      y1 = y2;
      if (iy==ny-2) y2 = 1;
      else          y2 = y1+dy;
   }
}


void style::DividePad(TPad *pin, int nx, int ny, double l, double r, double t, double b, TList * lout, Int_t &npad, const Int_t lastny)
{
  pin->SetTopMargin(0.);
  pin->SetBottomMargin(0.);
  pin->SetLeftMargin(0.);
  pin->SetRightMargin(0.); 
 
   int ix, iy, n=0;
   double x1, x2, y1, y2;
   double dx = ((1-r)*(1-l))/((1-r)*(1-l)*(nx-2)-r+2-l);
   double dl = dx/(1-l);
   double dy = ((1-t)*(1-b))/((1-t)*(1-b)*(ny-2)-t+2-b);
   double db = dy/(1-b);
   char *name  = new char [strlen(pin->GetName())+6];

   y1 = 0;
   y2 = db;
   for (iy=0; iy<lastny+1; iy++) {
      x1 = 0;
      x2 = dl;
      for (ix=0;ix<nx;ix++) {
         if (x1 > x2) continue;
         n++;
         sprintf(name,"%s_%d",pin->GetName(),n);
         TPad *pad = new TPad(name,name,x1,y1,x2,y2,0);lout->Add(pad);
         PadSetup(pad);

  pad->SetTopMargin(0.);
  pad->SetBottomMargin(0.);
  pad->SetLeftMargin(0.);
  pad->SetRightMargin(0.); 
 
         if (ix==0)    pad->SetLeftMargin(l);
         if (ix==nx-1) pad->SetRightMargin(r);
         if (iy==lastny) pad->SetTopMargin(t);
         if (iy==0)    pad->SetBottomMargin(b);
         x1 = x2;
         if (ix==nx-2) x2 = 1;
         else          x2 = x1+dx;
         pad->SetNumber(npad);npad++;
         pad->Draw();
         pad->SetTicks();
      }
      y1 = y2;
      if (iy==lastny-1) y2 = 1;
      else          y2 = y1+dy;
   }
}


void style::ToNaturalScale(TGraph* gr)
{
  for(Int_t ip=0; ip<gr->GetN(); ip++){
    Double_t xx=-999, yy=-999;
    gr->GetPoint(ip,xx,yy);
    gr->SetPoint(ip,TMath::Power(10,xx), yy);
  }
}

void style::ToNaturalScale(TGraphErrors* gr)
{
  for(Int_t ip=0; ip<gr->GetN(); ip++){
    Double_t xx=-999, yy=-999;
    gr->GetPoint(ip,xx,yy);
    //printf("%d %e %e\n",ip,xx,yy);
    gr->SetPoint(ip,TMath::Power(10,xx), yy);
  }
}

void style::ToNaturalScale(TGraphAsymmErrors* gr)
{
  for(Int_t ip=0; ip<gr->GetN(); ip++){
    const Double_t xx = gr->GetX()[ip];
    const Double_t exl = gr->GetEXlow()[ip];
    const Double_t exh = gr->GetEXhigh()[ip];

    const Double_t yy = gr->GetY()[ip];
    const Double_t eyl = gr->GetEYlow()[ip];
    const Double_t eyh = gr->GetEYhigh()[ip];

    //printf("%d %e %e\n",ip,xx,yy);
    gr->SetPoint(ip,TMath::Power(10,xx), yy);
    gr->SetPointError(ip, TMath::Power(10, xx) - TMath::Power(10, xx-exl), TMath::Power(10, xx+exh)-TMath::Power(10, xx), eyl, eyh);
  }
}

void style::ToNaturalScale(TAxis *ax)
{
  TAxis* oldx = (TAxis*)ax->Clone("oldx");
  ax->SetLimits(TMath::Power(10,oldx->GetXmin()), TMath::Power(10,oldx->GetXmax()));
  const Int_t nb = oldx->GetNbins();
  Double_t *bins = new Double_t[nb+1];
  bins[0]=TMath::Power(10,oldx->GetXmin());
  for(Int_t ii=1; ii<=nb; ii++){
    bins[ii]=TMath::Power(10,oldx->GetBinUpEdge(ii));
  }
  ax->Set(nb, bins);

  delete oldx;
  delete bins;
}

void style::ToNaturalScale(TH1 *hh)
{
  ToNaturalScale(hh->GetXaxis());
}


void style::UpdateLogX(TH1 *obj)
{
  TAxis * axis = obj->GetXaxis();
  double xmin = axis->GetXmin();
  double xmax = axis->GetXmax();
  axis->SetLimits(TMath::Power(10,xmin), TMath::Power(10,xmax));
  BinLogX(axis);
}

void style::UpdateLogX(TGraphAsymmErrors *obj)
{
  const Int_t np = obj->GetN();
  for(Int_t ii=0; ii<np; ii++){
    Double_t xx =-999, yy=-999;
    obj->GetPoint(ii,xx,yy);
    Double_t ex0 = obj->GetErrorXlow(ii);
    Double_t ex1 = obj->GetErrorXhigh(ii);
    const Double_t ey0 = obj->GetErrorYlow(ii);
    const Double_t ey1 = obj->GetErrorYhigh(ii);

    ex0 = TMath::Power(10, xx) - TMath::Power(10, xx-ex0);
    ex1 = TMath::Power(10, xx+ex1) - TMath::Power(10, xx);
    xx = TMath::Power(10, xx);

    obj->SetPoint(ii, xx, yy);
    obj->SetPointError(ii, ex0, ex1, ey0, ey1);
  }
}


void style::UpdateLogX(TGraphErrors *obj)
{
  const Int_t np = obj->GetN();
  for(Int_t ii=0; ii<np; ii++){
    Double_t xx =-999, yy=-999;
    obj->GetPoint(ii,xx,yy);
    Double_t ex = obj->GetErrorX(ii);
    const Double_t ey = obj->GetErrorY(ii);

    ex = TMath::Power(10, xx) - TMath::Power(10, xx-ex);
    xx = TMath::Power(10, xx);

    obj->SetPoint(ii, xx, yy);
    obj->SetPointError(ii, ex, ey);
  }
}


void style::PadSetup(TPad *currentPad, const Double_t currentLeft, const Double_t currentTop, const Double_t currentRight, const Double_t currentBottom)
{
  currentPad->SetTicks(1,1);
  currentPad->SetLeftMargin(currentLeft);
  currentPad->SetTopMargin(currentTop);
  currentPad->SetRightMargin(currentRight);
  currentPad->SetBottomMargin(currentBottom);

  currentPad->SetFillColor(0);//this is the desired one!!!
}

void style::AxisStyle(TAxis *ax, Bool_t kcen)
{
  ax->SetTickLength(fgkTickLength);

  ax->SetLabelFont(fgkTextFont);
  ax->SetLabelSize(fgkTextSize);
  ax->SetLabelOffset(fgkLabelOffset);

  ax->SetTitleFont(fgkTextFont);
  //printf("title %f text %f \n", fgkTitleSize, fgkTextSize);
  ax->SetTitleSize(fgkTitleSize);

  ax->CenterTitle(kcen);
}

void style::ResetStyle(TLegend *obj, Double_t mar)
{
  if(mar>0){
    obj->SetMargin(mar);
  }
  obj->SetFillStyle(-1);
  obj->SetBorderSize(-1);
  obj->SetTextFont(fgkTextFont);
  obj->SetTextSize(fgkTextSize*0.8);
}

void style::ResetStyle(TLatex *obj, const Double_t ff)
{
  obj->SetNDC();
  obj->SetTextFont(fgkTextFont);
  obj->SetTextSize(fgkTextSize*ff);
}

void style::ResetStyle(TGraph *obj)
{
  obj->SetMarkerSize(fgkMarkerSize);
  obj->SetLineWidth(fgkLineWidth);

  AxisStyle(obj->GetXaxis());
  AxisStyle(obj->GetYaxis());

  obj->GetXaxis()->SetTitleOffset(fgkXTitleOffset);
  obj->GetYaxis()->SetTitleOffset(fgkYTitleOffset);
}

void style::ResetStyle(TF1 * obj, Bool_t kcen)
{
  obj->SetMarkerSize(fgkMarkerSize);

  AxisStyle(obj->GetXaxis(), kcen);
  AxisStyle(obj->GetYaxis(), kcen);

  obj->GetXaxis()->SetTitleOffset(fgkXTitleOffset);
  obj->GetYaxis()->SetTitleOffset(fgkYTitleOffset);
}

void style::ResetStyle(TH1 * obj, TVirtualPad* cpad, Bool_t kcen)
{
  obj->SetMarkerSize(fgkMarkerSize);

  AxisStyle(obj->GetXaxis(), kcen);
  AxisStyle(obj->GetYaxis(), kcen);

  obj->GetXaxis()->SetTitleOffset(fgkXTitleOffset);
  obj->GetYaxis()->SetTitleOffset(fgkYTitleOffset);

  if(cpad){
    TPaletteAxis *palette = (TPaletteAxis*)obj->GetListOfFunctions()->FindObject("palette");
    if(!palette){
      printf("ResetStyle no palette!!\n"); 
      obj->GetListOfFunctions()->Print();
    }
    else{
      palette->SetX1NDC(1-cpad->GetRightMargin()+0.005);
      palette->SetX2NDC(1-cpad->GetRightMargin()/3*2);
      palette->SetY1NDC(cpad->GetBottomMargin());
      palette->SetY2NDC(1-cpad->GetTopMargin());
      palette->SetLabelFont(fgkTextFont);
      palette->SetLabelSize(fgkTextSize);
      palette->SetLabelOffset(fgkLabelOffset);
    }
  }

}

/*
void style::DrawLogo(TCanvas *cc, const Double_t x0, const Double_t y0, const TString tag)
{
  TPad *lpad=new TPad("lpad", "", x0,y0,x0+0.13,y0+0.2);
  PadSetup(lpad,0,0,0,0);
  lpad->Draw();
  lpad->cd();
  TASImage *logo = new TASImage("/u/xlu/.code/trunk/inc/2011-Nov-24-ALICE_PERFORMANCE_logo_BLACK_small_usage_design.eps");
  logo->Draw();

  cc->cd();
  TLatex * date = new TLatex(x0, y0-0.05, tag);
  ResetStyle(date, 0.8);
  date->Draw();
}
*/

void style::SetColor()
{
  gStyle->SetHistFillColor(0);
  //gStyle->SetFillColor(0);//it conflicts with color palette
  gStyle->SetFrameFillColor(0);
  gStyle->SetPadColor(0);
  gStyle->SetCanvasColor(0);
  gStyle->SetStatColor(0);
  gStyle->SetTitleFillColor(0);

  //---

  const Int_t nRGBs = 5;
  const Int_t nCont = 100;
  Double_t stops[nRGBs] = { 0.00, 0.34, 0.61, 0.84, 1.00 };
  Double_t red[nRGBs]   = { 0.00, 0.00, 0.87, 1.00, 0.51 };
  Double_t green[nRGBs] = { 0.00, 0.81, 1.00, 0.20, 0.00 };
  Double_t blue[nRGBs]  = { 0.51, 1.00, 0.12, 0.00, 0.00 };
  const Int_t cgc = TColor::CreateGradientColorTable(nRGBs, stops, red, green, blue, nCont);

  const Int_t nc = nCont;
  Int_t colors[nc];
  gStyle->SetNumberContours(nc); 
  for(Int_t ii=0; ii<nc; ii++){
    colors[ii]=cgc+ii;
  }
  gStyle->SetPalette(nc, colors);
}

void style::SetGlobalStyle(const Int_t lStat, Bool_t kcolor)
{
  // Set gStyle
  // From plain

  gStyle->SetFrameBorderMode(0);
  gStyle->SetFrameFillColor(0);
  gStyle->SetCanvasBorderMode(0);
  gStyle->SetPadBorderMode(0);
  gStyle->SetPadColor(10);
  gStyle->SetCanvasColor(10);
  gStyle->SetTitleFillColor(10);
  gStyle->SetTitleBorderSize(-1);
  gStyle->SetStatColor(10);
  gStyle->SetStatBorderSize(-1);
  gStyle->SetLegendBorderSize(-1);
  //
  gStyle->SetDrawBorder(0);
  gStyle->SetTextFont(fgkTextFont);
  gStyle->SetStatFont(fgkTextFont);
  gStyle->SetStatFontSize(fgkTextSize);
  gStyle->SetStatX(0.97);
  gStyle->SetStatY(0.98);
  gStyle->SetStatH(0.03);
  gStyle->SetStatW(0.3);
  gStyle->SetTickLength(fgkTickLength,"xy");
  gStyle->SetEndErrorSize(3);
  gStyle->SetLabelSize(fgkTextSize,"xyz");
  gStyle->SetLabelFont(fgkTextFont,"xyz"); 
  gStyle->SetLabelOffset(fgkLabelOffset,"xyz");
  gStyle->SetTitleFont(fgkTextFont,"xyz");  
  gStyle->SetTitleFont(fgkTextFont,"");  
  gStyle->SetTitleFontSize(fgkTitleSize);
  gStyle->SetTitleOffset(fgkXTitleOffset,"x");  
  gStyle->SetTitleOffset(fgkYTitleOffset,"y");  
  gStyle->SetTitleOffset(1.0,"z");  
  gStyle->SetTitleSize(fgkTitleSize,"xyz");  
  gStyle->SetTitleSize(fgkTitleSize,"");  
  gStyle->SetMarkerSize(fgkMarkerSize); 
  gStyle->SetPalette(1,0); 
  if (lStat){
    gStyle->SetOptTitle(1);
    gStyle->SetOptStat(1111);
    gStyle->SetOptFit(1111);
    }
  else {
    gStyle->SetOptTitle(0);
    gStyle->SetOptStat(0);
    gStyle->SetOptFit(0);
  }

  TGaxis::SetMaxDigits(3);
  gStyle->SetTitleBorderSize(-1);

  if(kcolor){
    SetColor();
  }

  gROOT->ForceStyle();
}

  
